﻿// 2025/10/21: 首个版本

using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Collections.Generic;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Avalonia.Controls;
using ASEva;
using ASEva.UIAvalonia;
using ASEva.Utility;

namespace CommonSource
{
    partial class SessionInfoEditor : DialogPanel
    {
        public SessionInfoEditor() // For designer
        {
            InitializeComponent();
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
        }

        public SessionInfoEditor(SessionIdentifier session, String iconResourceName = null)
        {
            InitializeComponent();
            SetResizableMode(400, 400, 400, 500);
            language = new LanguageSwitch(Resources, AgencyLocal.GetAppLanguage());
            Icon = ResourceLoader.Load(iconResourceName)?.ToAvaloniaWindowIcon();
            Title = language["title"];

            model = new SessionInfoEditorViewModel(this, session, language);
            model.InitializeInfo();
            model.CloseRequest += delegate { Close(); };
            DataContext = model;
        }

        private LanguageSwitch language;
        private SessionInfoEditorViewModel model;
    }

    partial class SessionInfoEditorViewModel(Control view, SessionIdentifier session, LanguageSwitch language) : ObservableObject
    {
        public async void InitializeInfo()
        {
            view.IsEnabled = false;

            Task[] tasks =
            [
                AgencyAsync.GetHostPosixTimeModel(session),
                AgencyAsync.GetSessionLength(session),
                AgencyAsync.GetSessionHostSync(session),
                AgencyAsync.GetSessionComment(session),
                AgencyAsync.GetSessionProperties(session),
            ];
            await Task.WhenAll(tasks);

            var hostTimeModel = (tasks[0] as Task<PosixTimeModel>).Result;
            var interval = (tasks[1] as Task<double?>).Result;
            var hostSync = (tasks[2] as Task<bool>).Result;
            var comment = (tasks[3] as Task<string>).Result;
            var properties = (tasks[4] as Task<Dictionary<string, string>>).Result;

            if (hostTimeModel == null)
            {
                StartTime = language["unknown"];
            }
            else
            {
                var hostLocalStartTime = (new DateTime(1970, 1, 1, 0, 0, 0)).AddMilliseconds(hostTimeModel.StartPosix);
                StartTime = hostLocalStartTime.ToString(language["date-time-format"]) + "ms";
            }

            if (interval == null)
            {
                Duration = language["unknown"];
            }
            else
            {
                if (interval.Value < 1)
                {
                    Duration = language["zero-sec"];
                }
                else
                {
                    var span = TimeSpan.FromSeconds(interval.Value);
                    var days = (int)span.TotalDays;
                    var hours = span.Hours;
                    var minutes = span.Minutes;
                    var seconds = span.Seconds;
                    var ms = span.Milliseconds;
                    var text = "";
                    text += (days > 0 ? (days + language["days"]) : "");
                    text += (hours > 0 ? (hours + language["hours"]) : "");
                    text += (minutes > 0 ? (minutes + language["minutes"]) : "");
                    text += (seconds > 0 ? (seconds + language["seconds"]) : "");
                    text += (ms > 0 ? (ms + language["milliseconds"]) : "");
                    Duration = text;
                }
            }

            Comment = comment ?? "";
            HostSync = hostSync;

            if (properties != null)
            {
                foreach (var item in properties) PropertyItems.Add(new PropertyItem(item.Key, item.Value));
            }

            view.IsEnabled = true;
        }

        [ObservableProperty]
        private String startTime;

        [ObservableProperty]
        private String duration;

        [ObservableProperty]
        private bool hostSync;

        [ObservableProperty]
        private string comment;

        [RelayCommand]
        private void AddProperty()
        {
            var newItem = new PropertyItem(language["new-property"], "");
            PropertyItems.Add(newItem);
            SelectedPropertyItem = newItem;
        }

        [RelayCommand]
        private void RemoveProperty()
        {
            if (SelectedPropertyItem != null) PropertyItems.Remove(SelectedPropertyItem);
        }

        public partial class PropertyItem(String _key, String _value) : ObservableObject
        {
            [ObservableProperty]
            private string key = _key;

            [ObservableProperty]
            private string value = _value;
        }

        [ObservableProperty]
        private ObservableCollection<PropertyItem> propertyItems = new();

        [ObservableProperty]
        private PropertyItem selectedPropertyItem;

        public bool ClientSide => AgencyLocal.ClientSide;

        [RelayCommand]
        private async Task OpenFolder()
        {
            var path = AgencyLocal.GetSessionPath(session);
            if (!AgencyLocal.StartProcess(path)) await AgencyLocal.PopupError(language["failed-open-folder"]);
        }

        [ObservableProperty]
        private bool deletingSession = false;

        [RelayCommand]
        private async Task DeleteSession()
        {
            DeletingSession = true;
            if (await AgencyAsync.RemoveSession(session, false)) CloseRequest?.Invoke(this, EventArgs.Empty);
            else DeletingSession = false;
        }

        [RelayCommand]
        private async Task Confirm()
        {
            var properties = new Dictionary<String, String>();
            for (int i = 0; i < PropertyItems.Count; i++)
            {
                var key = PropertyItems[i].Key;
                var value = PropertyItems[i].Value;

                if (String.IsNullOrEmpty(key) || value == null) continue;

                if (properties.ContainsKey(key))
                {
                    await AgencyLocal.PopupError(language.Format("repeated-key", key));
                    return;
                }
                else properties[key] = value;
            }

            CloseRequest?.Invoke(this, EventArgs.Empty);

            await AgencyAsync.SetSessionHostSync(session, HostSync);
            await AgencyAsync.SetSessionComment(session, Comment);
            await AgencyAsync.SetSessionProperties(session, properties);
        }

        public event EventHandler CloseRequest;
    }
}